home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / presto / presto10.lha / src / parallel.h < prev    next >
C/C++ Source or Header  |  1991-12-11  |  6KB  |  164 lines

  1. #ifndef __presto__parallel_h__
  2. #define __presto__parallel_h__
  3.  
  4. /* $Copyright:    $
  5.  * Copyright (c) 1984, 1985, 1986 Sequent Computer Systems, Inc.
  6.  * All rights reserved
  7.  *  
  8.  * This software is furnished under a license and may be used
  9.  * only in accordance with the terms of that license and with the
  10.  * inclusion of the above copyright notice.   This software may not
  11.  * be provided or otherwise made available to, or used by, any
  12.  * other person.  No title to or ownership of the software is
  13.  * hereby transferred.
  14.  */
  15.  
  16. /* $Header: /crg2/bruces2/rbk/C++/Presto/src/RCS/parallel.h,v 1.2 88/03/24 09:52:47 rbk Exp $
  17.  *
  18.  * parallel.h
  19.  *    Definitions for use in parallel, shared-memory programs.
  20.  */
  21.  
  22. /* $Log:    parallel.h,v $
  23.  *
  24.  * 90/01/14 jef
  25.  * HC_Spinlock fails sporadically when 16 processors are contending for a
  26.  * lock.  Visual inspection of code in hc_slock_asm.h SEEMS to indicate an
  27.  * 'off-by-1' problem - the private lock data is in x [procid][16] in an
  28.  * array indexed [p][16] (i.e., the private lock data is *ACTUALLY* dealt
  29.  * with in x [procid +1 ][0]!!).  Everything would still work fine, except
  30.  * for processor 16, whose private data would be found one byte off the end
  31.  * of the array (and when that byte changes value, processor 16 gets the
  32.  * lock, even if it shouldn't have!).  Modifying the hc_slock_t structure
  33.  * to be [procs][17] seems to solve the problem - however, the real
  34.  * problem is in the code and/or comments in hc_slock_asm.h.
  35.  *
  36.  * 89/12/28 jef
  37.  * Add support for a second type of spinlock which works well in
  38.  * high lock contention situations (after original by raj).
  39.  *
  40.  * Revision 1.2  88/03/24  09:52:47  rbk
  41.  * #ifdef ns32000 around ALM fuss.  Can't use system version of this file
  42.  * since C++ doesn't understand asm-functions yet.
  43.  * 
  44.  * Revision 1.1  88/03/22  15:26:42  rbk
  45.  * Initial revision
  46.  * 
  47.  */
  48.  
  49. #ifdef sequent
  50. #ifdef i386
  51.  
  52. /*
  53.  *  Data structure for regular spinlock.
  54.  *  A "lock" is a byte of memory, initialized to zero (unlocked).
  55.  */
  56.  
  57. typedef unsigned char    slock_t;
  58.  
  59. /*
  60.  *  Data structure for high-contention spinlock based on queueing.
  61.  *
  62.  *  In a regular spinlock, all threads requesting the lock spin, performing
  63.  *  test-and-set operations on a single shared memory location.  The
  64.  *  resulting cache invalidation traffic quickly saturates the bus with
  65.  *  only a small number of spinning processors, impacting the performance
  66.  *  of the thread holding the lock (by interfering with it's ability to
  67.  *  access memory) and causing a rapid falloff in performance.
  68.  *
  69.  *  The queue-based spinlock is designed to eliminate this problem.  Threads
  70.  *  spin on a private location instead of a shared location, eliminating the
  71.  *  cache invalidation traffic.  To release a lock, the thread holding the
  72.  *  lock simply sets the private location that the next waiter is spinning on
  73.  *  (in this case no atomic instruction is needed).
  74.  *
  75.  *  Since a spinning thread does not relinquish it's processor, the
  76.  *  lock data structure need only support NUMPROCS threads.  In this
  77.  *  implementation, the DYNIX process id (from getpid ()) of the requesting
  78.  *  thread is used to index into the lock data structure.  Processor ids
  79.  *  are converted to range from 1 to NUMPROCS (as opposed to 0 to NUMPROCS-1
  80.  *  as in PRESTO).  Row 0 of the array is reserved for use in indicating the
  81.  *  identity of the last requestor of the lock.  It also stores a copy of
  82.  *  the last requestor's private data area.
  83.  *
  84.  *  The private location which each processor spins on while it waits to
  85.  *  acquire the lock is (supposedly) located at x [last_procid] [15], i.e.,
  86.  *  it spins on the private location of the last processor which requested
  87.  *  the lock (NOTE:  from the code in hc_slock_asm.h, I believe this
  88.  *  location is ACTUALLY x [last_procid] [*16*], which is why I increased
  89.  *  the length of each row to 17 (jef)).  I believe that the extra
  90.  *  15 bytes in each row are used to force each private location into a
  91.  *  separate cache line on the 386, thus eliminating extra cache coherency
  92.  *  traffic when a private location is set by a releasing lock holder.
  93.  *
  94.  *  See comments in hc_slock_asm.h for more details.
  95.  */
  96.  
  97. #define HC_S_LOCK_SIZE (NUMPROCS+1)
  98. typedef struct hc_slock_t { unsigned char x[HC_S_LOCK_SIZE][17]; };
  99.  
  100. #endif /* 386 */
  101. #endif /* sequent */
  102.  
  103. #define    L_UNLOCKED    0
  104. #define    L_LOCKED    1
  105.  
  106. /*
  107.  * Was a conditional lock request granted (L_SUCCESS) or denied (L_FAILED)
  108.  */
  109. #define L_FAILED    0
  110. #define L_SUCCESS    1
  111.  
  112. /*
  113.  * A "barrier" allows multiple processes to synchronize by having
  114.  * all of them exit the barrier construct simultaneously.
  115.  *
  116.  * This version assumes <= 255 processes, fits in one 4-byte integer,
  117.  * and is based on spin-locks.
  118.  */
  119.  
  120. typedef struct    {
  121.     slock_t        b_mutex;    /* mutual exclusion */
  122.     unsigned char    b_limit;    /* number participants */
  123.     unsigned char    b_count;    /* state counter */
  124.     unsigned char    b_useno;    /* current use # (state flag) */
  125. } sbarrier_t;                /* 's' for "spin"-barrier */
  126.  
  127.  
  128. /* other useful declarations
  129.  */
  130.  
  131. extern  caddr_t sbrk(int);
  132. extern  char    *shmalloc(unsigned);
  133. extern  caddr_t shsbrk(caddr_t);
  134.  
  135.  
  136. /*
  137.  * Convenience definitions.
  138.  */
  139.  
  140. #ifndef    NULL
  141. #define    NULL        0
  142. #endif
  143.  
  144. /*
  145.  * Various globally used data.
  146.  */
  147.  
  148. extern    int    errno;
  149.  
  150. extern    int    _shm_fd;        /* fd for shared data mapped file */
  151. #ifdef    ns32000
  152. extern    char    *_alm_base;        /* virt addr of mapped ALM's */
  153. #endif /*    ns32000 */
  154. extern    int    _pgoff;            /* getpagesize() - 1 */
  155.  
  156. /*
  157.  * PGRND() rounds up a value to next page boundary.
  158.  */
  159.  
  160. #define    PGRND(x)    (char *) (((int)(x) + _pgoff) & ~_pgoff)
  161.  
  162.  
  163. #endif /* __presto__parallel_h__ */
  164.